Rules for Tools/Event Structure
Event Structure
Bars&Pipes uses the Event structure to describe MIDI events, both as they flow through
the PipeLine, and when they are recorded in a Track:
struct Event {
struct Event *next; /* Next Event in list. */
long time; /* When this Event occurs. */
char type; /* What type of Event. */
unsigned char status; /* MIDI status. */
unsigned char byte1; /* First byte of data. */
unsigned char byte2; /* Second byte of data. */
long data; /* Extra storage. */
struct Tool *tool; /* Tool to process this. */ };
`next'
This points to the next Event in the linked list of Events that
make up a sequence. Almost all Bars&Pipes data structures are
arranged in linked lists. This provides a great degree of
flexibility because linked lists can be any length. Also, since
the pointer to the next record in a Bars&Pipes linked list is
always the first field of the structure, Bars&Pipes can use
generic list handling routines to process different types of
linked lists.
`time'
This specifies the absolute time of the Event. Bars&Pipes
measures time in clocks, with 192 clocks per quarter note. An
example time of 384 corresponds to the beginning of the third beat
of measure one in the song. `time' is very useful because you can
write Tools that alter the timing of events by changing this
number. Good examples are the Quantize and Delay Tools. If the
transport is not rolling when an event occurs, time contains a
negative number.
`type'
This specifies what type of data is stored in the Event. Choices
include `EVENT_VOICE', for a MIDI performance Event, and
`EVENT_LYRIC', for a Lyric in the Song Parameters. Only
`EVENT_VOICE' Events flow through the PipeLine; therefore Tools
need only concern themselves with this one type. When a Tool is
in a ToolPad, it receives Events with the `EVENT_PADEDIT' bit set,
in addition to `EVENT_VOICE'. The `EVENT_PADEDIT' bit tells the
Tool that it is processing a static note in a sequence, rather
than a real-time note flowing through a PipeLine. See Event Types.
`status' `byte1' `byte2'
If this is a MIDI Event, these three bytes carry the actual MIDI
data. `status' determines the actual MIDI Event type, while
`byte1' and `byte2' carry the appropriate data. The MIDI spec
breaks status down into two nibbles: the high nibble selects the
type of Event, while the low nibble selects one of sixteen MIDI
channels. Bars&Pipes, because its PipeLine does not recognize
MIDI channels, always clears the low nibble. In case you don't
have the MIDI spec, here's a rundown on the MIDI status codes (see
MIDI Status Types):
`MIDI_NOTEON'
Note On Event. `byte1' holds the numeric value of the note
to play, while `byte2' holds the velocity of the note. Both
numbers range from 0 to 127. Middle C is 60. If the note is
in the PipeLine, there are two separate events that describe
it: a `MIDI_NOTEON' and a `MIDI_NOTEOFF' event. If the Note
is in a sequence, it is represented by one `MIDI_NOTEON'
Event that holds a note duration in addition to the note
value and velocity (see Note Events.) Unlike the MIDI spec, a
`MIDI_NOTEOFF' Event may not be represented by a
`MIDI_NOTEON' with a velocity of 0.
`MIDI_NOTEOFF'
Note Off Event. `byte1' holds the numeric value of the note
to stop playing, while `byte2' is ignored.
`MIDI_PTOUCH'
Polyphonic Key Pressure Event. `byte1' holds the numeric
value of the note, while `byte2' holds its key pressure, a
value from 0 to 127.
`MIDI_CCHANGE'
Control Change Event. There are 121 types of Continuous
Controller Events. `byte1' specifies the Control Change
type. For example, 1 indicates the modulation wheel setting,
7 indicates overall volume, and 10 indicates the pan setting.
`byte2' carries the data, once again ranging from 0 to 127.
Control Change types 121 through 127 are special cases. Of
importance to Bars&Pipes are 121, the all controllers off
command, and 123, the all notes off command. Bars&Pipes
sends both of these down each PipeLine whenever the user
stops the sequencer.
`MIDI_PCHANGE'
Program Change Event. This command sets the Program, or
Patch, that the synthesizer plays. `byte1' carries the
Program, a number from 0 to 127, and `byte2' is ignored.
`MIDI_MTOUCH'
Monophonic Key Pressure Event. Like `MIDI_PTOUCH', this
broadcasts the key pressure, but for the keyboard as a whole,
rather than on a note-by-note basis. `byte1' carries the key
pressure and `byte2' is not used.
`MIDI_PBEND'
Pitch Bend Event. This transmits the current position of the
Pitch Bend wheel. Pitch Bend is a high resolution number,
ranging from 0, for a complete bend down, to 0x3FFF for the
maximum bend up. A center pitch bend (no change) is 0x2000.
The bend value is broken into two components, the high seven
bits and the low seven bits of the bend. The high bits are
stored in `byte2', the low bits in byte.
`data'
This is really just padding; however, if this is a `NoteEvent'
structure (see Note Events) the upper two bytes carry the note
duration.
`tool'
This points to the Tool that is to process the Event.